/**************************************************************************
 *
 *  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 *  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
 *  PURPOSE.
 *
 *  Copyright (C) 1992 - 1997 Microsoft Corporation.  All Rights Reserved.
 *
 **************************************************************************/

#include <windows.h>
#include <windowsx.h>
#include <commdlg.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <direct.h>
#include <mmsystem.h>
#include <digitalv.h>
#include "video.h"


//----------------------------------------------------------------------------

#define OPEN_AVI_VIDEO "open avivideo"
#define CLOSE_AVI_VIDEO "close avivideo"
#define MOV_SEEK_TO_START "seek mov to start"
#define MOV_SEEK_TO_END "seek mov to end"
#define MOV_CLOSE "close mov"
#define MOV_SOURCE "where mov source"
#define MOV_OPEN_FORMAT "open %s alias mov style child parent %d"
#define MOV_SHOW "window mov state show"
#define MOV_HANDLE "status mov window handle"
#define MOV_REVERSE "play mov reverse notify"
#define MOV_FORWARD "play mov notify"
#define MOV_PAUSE "pause mov"
#define MOV_FORWARD_STEP "step mov by 1"
#define MOV_REVERSE_STEP "step mov reverse by 1"

BOOL initAVI(void);
void termAVI(void);
void positionMovie(void);
void fileCloseMovie(void);
void fileOpenMovie(void);
void playMovie(int);
void seekMovie(int);
void stepMovie(int);


//----------------------------------------------------------------------------
void Init_Video(HINSTANCE hInstance, HWND hWnd)
{
	ghInst = hInstance;
	ghwndParent = hWnd;
	ghwndMovie = NULL;
	initAVI();
	fileOpenMovie();
}

void Destroy_Video(void)
{
	fileCloseMovie();
	termAVI();
}

void Play_Video(BOOL playing)
{
	if (playing)
	{
		mciSendString(MOV_FORWARD, NULL, 0, ghwndParent);
	}
	else
	{
		mciSendString(MOV_PAUSE, NULL, 0, NULL);
	}
}

void Pause_Video(void)
{
	mciSendString(MOV_PAUSE, NULL, 0, NULL);
}

void Stop_Video(void)
{
	mciSendString(MOV_PAUSE, NULL, 0, NULL);
	mciSendString(MOV_SEEK_TO_START, NULL, 0, NULL);
}

void Replay_Video(void)
{
	mciSendString(MOV_FORWARD, NULL, 0, ghwndParent);
}

/*--------------------------------------------------------------+
| initAVI - initialize avi libraries				|
|								|
+--------------------------------------------------------------*/
BOOL initAVI(void)
{
	return mciSendString(OPEN_AVI_VIDEO, NULL, 0, NULL) == 0;
}

/*--------------------------------------------------------------+
| termAVI - Closes the opened AVI file and the opened device    |
|           type.                                               |
|                                                               |
+--------------------------------------------------------------*/
void termAVI(void)
{
	mciSendString(CLOSE_AVI_VIDEO, NULL, 0, NULL);
}

/*--------------------------------------------------------------+
| positionMovie - sets the movie rectange <rcMovie> to be	|
|		centered within the app's window.		|
|								|
+--------------------------------------------------------------*/
void positionMovie(void)
{
	RECT rcMovie;
	RECT rcClient;
	RECT rcMovieBounds;
	char achRect[128];
	char *p;

	/* if there is no movie yet then just get out of here */
	if (!gfMovieOpen)
		return;

	GetClientRect(ghwndParent, &rcClient);	/* get the parent windows rect */
	
	/* get the original size of the movie */
	mciSendString(MOV_SOURCE, achRect, sizeof(achRect), NULL);

	SetRectEmpty(&rcMovieBounds);	// zero out movie rect
	p = achRect;	// point to rectangle string returned by where command
	while (*p == ' ') p++;	// skip over starting spaces
	while (*p != ' ') p++;	// skip over the x (which is 0)
	while (*p == ' ') p++;	// skip over spaces between x and y
	while (*p != ' ') p++;	// skip over the y (which is 0)
	while (*p == ' ') p++;	// skip over the spaces between y and width

	/* now find the width */
	for (; *p >= '0' && *p <= '9'; p++)
		rcMovieBounds.right = (10 * rcMovieBounds.right) + (*p - '0');
	while (*p == ' ') p++;	// skip spaces between width and height

	/* now find the height */
	for (; *p >= '0' && *p <= '9'; p++)
		rcMovieBounds.bottom = (10 * rcMovieBounds.bottom) + (*p - '0');

	/* figure out where to position the window at */
	rcMovie.left = (rcClient.right/2) - (rcMovieBounds.right / 2);
	rcMovie.top = (rcClient.bottom/2) - (rcMovieBounds.bottom / 2);
	rcMovie.right = rcMovie.left + rcMovieBounds.right;
	rcMovie.bottom = rcMovie.top + rcMovieBounds.bottom;

	/* reposition the playback (child) window */
	MoveWindow(ghwndMovie, rcMovie.left, rcMovie.top,
		rcMovieBounds.right, rcMovieBounds.bottom, TRUE);
}

/*--------------------------------------------------------------+
| fileCloseMovie - close the movie and anything associated	|
|		   with it.					|
|								|
| This function clears the <gfPlaying> and <gfMovieOpen> flags	|
|								|
+--------------------------------------------------------------*/
void fileCloseMovie(void)
{
	/* close current playing movie */
	mciSendString(MOV_CLOSE, NULL, 0, NULL);
	
	gfPlaying = FALSE;	// can't be playing any longer
	gfMovieOpen = FALSE;	// no more movies open
	
	/* cause a total repaint to occur */
	InvalidateRect(ghwndParent, NULL, TRUE);
	UpdateWindow(ghwndParent);
}


/*--------------------------------------------------------------+
| fileOpenMovie - open an AVI movie. Use CommDlg open box to	|
|	        open and then handle the initialization to	|
|		show the movie and position it properly.  Keep	|
|		the movie paused when opened.			|
|								|
|		Sets <gfMovieOpened> on success.			|
+--------------------------------------------------------------*/
void fileOpenMovie(void)
{
	char szCommand[BUFSIZE];
	DWORD  dw;

	/* we got a filename, now close any old movie and open */
	/* the new one.					*/
	if (gfMovieOpen)
		fileCloseMovie();	

	/* we have a .AVI movie to open, use MCI */
	/*
	| build up the string -
	| open alias mov parent HWND FILENAME
	| to pass to mciSendString
	*/
	wsprintf(szCommand,MOV_OPEN_FORMAT, "..\\Data\\Help.AVI", (int)ghwndParent);

	/* try to open the file */
	if (mciSendString(szCommand, NULL, 0, NULL) == 0){
		gfMovieOpen = TRUE;
		/* we opened the file o.k., now set up to */
		/* play it.				   */
		mciSendString(MOV_SHOW, NULL, 0, NULL);
		/* get the window handle */
		if ((dw = mciSendString(MOV_HANDLE, szCommand, sizeof(szCommand),
						NULL)) == 0L)
			ghwndMovie = (HWND)atoi(szCommand);
		else {
			mciGetErrorString(dw, szCommand, sizeof(szCommand));
			MessageBox(ghwndParent, szCommand, NULL, MB_ICONEXCLAMATION|MB_OK);
		}
		/* now get the movie centered */
		positionMovie();
	} else {
		/* generic error for open */
		LoadString( ghInst, IDS_NOOPEN, gszBuffer, BUFSIZE );
		MessageBox(ghwndParent, gszBuffer, NULL, MB_ICONEXCLAMATION|MB_OK);
		gfMovieOpen = FALSE;
	}

	/* cause an update to occur */
	InvalidateRect(ghwndParent, NULL, FALSE);
	UpdateWindow(ghwndParent);
}

/*--------------------------------------------------------------+
| playMovie - play/pause the movie depending on the state	|
|		of the <gfPlaying> flag.			|
|								|
| This function sets the <gfPlaying> flag appropriately when done|
|								|
+--------------------------------------------------------------*/
void playMovie(int nDirection)
{
	gfPlaying = !gfPlaying;	/* swap the play flag */
	if(!nDirection)
		gfPlaying = FALSE;	/* nDirection == NULL means PAUSE */

	/* play/pause the AVI movie */
	if (gfPlaying){
		if (nDirection == VID_RPLAY){
			mciSendString(MOV_REVERSE, NULL, 0, ghwndParent);
		} else {
			mciSendString(MOV_FORWARD, NULL, 0, ghwndParent);
		}
	} else {
		/* tell it to pause */
		mciSendString(MOV_PAUSE, NULL, 0, NULL);
	}
}

/*--------------------------------------------------------------+
| seekMovie - seek in the movie depending on the wAction.	|
|	      Possible actions are IDM_HOME (start of movie) or	|
|	      IDM_END (end of movie)				|
|								|
|	      Always stop the play before seeking.		|
|								|
+--------------------------------------------------------------*/
void seekMovie(int nAction)
{
	/* first stop the movie from playing if it is playing */
	if (gfPlaying){
		playMovie(0);	
	}
	
	if (nAction == VID_HOME){
		/* home the movie */
		mciSendString(MOV_SEEK_TO_START, NULL, 0, NULL);
	} else if (nAction == VID_END){
		/* go to the end of the movie */
		mciSendString(MOV_SEEK_TO_END, NULL, 0, NULL);
	}
}

/*--------------------------------------------------------------+
| stepMovie - step forward or reverse in the movie.  wDirection	|
|		can be IDM_STEP (forward) or IDM_RSTEP (reverse)|
|								|
|		Again, stop the play if one is in progress.	|
|								|
+--------------------------------------------------------------*/
void stepMovie(int nDirection)
{
	if (gfPlaying)
		playMovie(0);  /* turn off the movie */

	if (nDirection == VID_STEP)
		mciSendString(MOV_FORWARD_STEP, NULL, 0, NULL);
	else
		mciSendString(MOV_REVERSE_STEP, NULL,0, NULL);
}
